The built-in language consists of a simple RISC-like instruction set.

Model:
------

The flags register has only CY and Z flags.
Available is 256 of 32-bit registers named R0..Rff.
W0Rn is the lower word of register Rn, while W1Rn is the upper word of register Rn.
B0Rn, B1Rn, B2Rn and B3Rn are the bytes of register Rn in the order from the lowest to the highest.
If the destination operand size is smaller than the source operand size, then the source operand is zero-padded,
if it is larger then it is cropped.

Instruction set:
----------------
MOV
AND, OR, XOR, TEST
INC, DEC
ADD, SUB, CMP, MUL, DIV, MOD
RCL, RCR, ROL, ROR, SHL, SHR
JMP
JZ, JNZ, JC, JNC, JA

Operands:
---------
Destination (dst) operand can be either register or memory reference.
register
[register]
[address]

Source (src) operand can be register, immediate value or memory reference.
register
immediate
[register]
[address]

INC/DEC has only dst operand
JMPs has only immediate or register operand
MUL has three operands: MUL dst,src,reg. It stores the result of dst*src into the pair reg:dst, where reg is a 32-bit register.
All other instructions has two operands: dst,src

The [address] operand refers to the offset address in the datablock in use.

You can specify the size of the memory reference operand by using prefix BYTE/WORD/DWORD.
If not specified, the size of the memory reference operand is determined by the other operand size,
if it is register or specified memory reference. Otherwise it defaults to BYTE.

Environment:
------------
Function returns its value in register r0.
Parameters to procedure/function are passed in registers Rff,Rfe,...; the first parameter is in Rff, the second in Rfe etc.
There are two separate memory spaces, the source and the destination one.
All memory source operands work in the source memory space and all memory destination operands work in the destination memory space.
All memory operations are safe, i.e. when reading out of allocated memory you get 0, write to an unallocated memory does nothing.

Machine code:
-------------
Special instruction formats:
NOP     00

INC     xx000001 OPERAND
DEC     xx000010 OPERAND
where xx specifies operand:
 00 register
 10 [register]
 11 [address]

JMP WORD immediate      14
JNC WORD immediate      15
JNZ WORD immediate      16
JA  WORD immediate      17
JC  WORD immediate      19
JC  WORD immediate      1b
JZ  WORD immediate      1e
JZ  WORD immediate      1f
If the highest bit of opcode is set (i.e. opcode 94..a3), then the immediate operand is replaced by the operand WORD register.
Opcodes $18,$1a,$1c,$1d,$20,$21,$22 and $23 are conditional jumps with the condition never satisfied.

general instruction format:
BYTE opcode BYTE ops OPERANDS

Opcodes:
MOV     03
AND     04
OR      05
XOR     06
TEST    07
ADD     08
SUB     09
CMP     0a
MUL     0b
DIV     0c
MOD     0d
RCL     0e
RCR     0f
ROL     10
ROR     11
SHL     12
SHR     13

Operand specification (ops):
Lower nibble specifies dst, upper nibble src operand.
0000 - register
0001 - immediate
0010 - [register]
0011 - [address]

OPERANDS:
Register is specified by two bytes:
 first byte specifies the register size and position
  0000 - DWORD
  0100 - WORD 0
  0101 - WORD 1
  1000 - BYTE 0
  1001 - BYTE 1
  1010 - BYTE 2
  1011 - BYTE 3
 second byte specifies the number of the register

Immediate operand size is specified by the size of dst operand.
It consists of just 'size' bytes.

Memory reference operands
[register]
 BYTE memsize WORD register specification
[address]
 BYTE memsize DWORD address

memsize:
  0000 - DWORD
  0100 - WORD
  1000 - BYTE

MUL instruction has one extra byte, which specifies the second destination operand (32-bit register).

Examples:
---------
Standard checksum routine:

0310080000      MOV B0R0,0
060000010001    XOR R1,R1
0200ff          DEC Rff
@loop:
06200000080001  XOR R0,byte [R1]
010001          INC R1
0200ff          DEC Rff
160e00          JNZ @loop

Gremlin 2 checksum routine:

031004000000            MOV W0R0,0
031004010300            MOV W0R1,3
091000ff05000000        SUB Rff,5
@loop:
08200000080401          ADD R0,byte [W0R1]
010001                  INC R1
0200ff                  DEC Rff
161400                  JNZ @loop


Busy soft decryption routine: (xxx=4 protection bits from the header)

    DEC  RFE
    MOV  R1,BYTE [RFE]
    SHR  R1,4
    OR   B0R1,xxx
    DEC  RFE
    DEC  RFE
    MOV  R0,RFE
    MOV  R2,1
    XOR  R3,R3
@label:
    ADD  B0R1,3B
    MOV  BYTE [R3],BYTE [R2]
    XOR  BYTE [R3],R1
    INC  R2
    INC  R3
    DEC  RFE
    JNZ  @label
    SHL  R0,3

Gremlin 2.5 decryption routine:

 xor r2,r2
 mov w0r5,word [1]
 mov r0,w0r5
 mov r1,3
 sub rfe,5
@8bits:
 mov b0r4,8
 mov b0r3,[r1]
@srcloop:
 shl b0r3,1
 dec b0r4
 jc @found
 jnz @srcloop
@src1:
 inc r1
 dec rfe
 jnz @8bits
 jmp @end
@found:
 mov b1r4,8
 sub b1r4,b0r4
@loop1:
 mov b0r3,[r1]
 shl b0r3,b1r4
 inc r1
 dec rfe
 jz @end
 mov b1r3,[r1]
 shr b1r3,b0r4
 or b0r3,b1r3
 mov [r2],b0r3
 inc r2
 dec w0r5
 jz @end2
 test b0r5,0f
 jnz @loop1
 test b0r4,b0r4
 jz @src1
 mov b0r3,[r1]
 shl b0r3,b1r4
 jmp @srcloop
@end:
 sub r0,w0r5
@end2:
 shl r0,3
